package com.zy.composeworld.ui.screens.image.image

import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Divider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.geometry.center
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ColorMatrix
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.ImageShader
import androidx.compose.ui.graphics.LinearGradientShader
import androidx.compose.ui.graphics.Matrix
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.RadialGradientShader
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shader
import androidx.compose.ui.graphics.ShaderBrush
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.TileMode
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.asComposePath
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.clipPath
import androidx.compose.ui.graphics.drawscope.inset
import androidx.compose.ui.graphics.drawscope.scale
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.imageResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.unit.toSize
import androidx.graphics.shapes.CornerRounding
import androidx.graphics.shapes.Morph
import androidx.graphics.shapes.RoundedPolygon
import androidx.graphics.shapes.star
import androidx.graphics.shapes.toPath
import coil.compose.AsyncImage
import com.zy.composeworld.R
import kotlin.math.max
import kotlin.math.roundToInt


@OptIn(ExperimentalFoundationApi::class)
@Preview
@Composable
fun ImagePager007() {

    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
    ) {

        item {
            TextHead(text = "Compose 中的形状")
            TextHead(text = "创建多边形")

            Box(
                modifier = Modifier
                    .drawWithCache {
                        val roundedPolygon = RoundedPolygon(
                            numVertices = 6,
                            radius = size.minDimension / 2,
                            centerX = size.width / 2,
                            centerY = size.height / 2
                        )
                        val roundedPolygonPath = roundedPolygon
                            .toPath()
                            .asComposePath()
                        onDrawBehind {
                            drawPath(roundedPolygonPath, color = Color.Blue)
                        }
                    }
                    .size(150.dp)
            )

        }

        item {
            TextHead(text = "将多边形的角设置为圆角")
            Row {

                Box(
                    modifier = Modifier
                        .drawWithCache {
                            val roundedPolygon = RoundedPolygon(
                                numVertices = 6,
                                radius = size.minDimension / 2,
                                centerX = size.width / 2,
                                centerY = size.height / 2,
                                rounding = CornerRounding(32f, 0.5f)
                            )
                            val roundedPolygonPath = roundedPolygon
                                .toPath()
                                .asComposePath()
                            onDrawBehind {
                                drawPath(roundedPolygonPath, color = Color.Blue)
                            }
                        }
                        .size(150.dp)
                )


                Box(
                    modifier = Modifier
                        .drawWithCache {
                            val roundedPolygon = RoundedPolygon(
                                numVertices = 3,
                                radius = size.minDimension / 2,
                                centerX = size.width / 2,
                                centerY = size.height / 2,
                                rounding = CornerRounding(32f, 0.5f)
                            )
                            val roundedPolygonPath = roundedPolygon
                                .toPath()
                                .asComposePath()
                            onDrawBehind {
                                drawPath(roundedPolygonPath, color = Color.Blue)
                            }
                        }
                        .size(150.dp)
                )

            }

            Row {
                Box(
                    modifier = Modifier
                        .drawWithCache {
                            val roundedPolygon = RoundedPolygon(
                                numVertices = 3,
                                radius = size.minDimension / 2,
                                centerX = size.width / 2,
                                centerY = size.height / 2,
                                rounding = CornerRounding(
                                    size.minDimension / 10f,
                                    smoothing = 0.1f
                                )
                            )
                            val roundedPolygonPath = roundedPolygon
                                .toPath()
                                .asComposePath()
                            onDrawBehind {
                                drawPath(roundedPolygonPath, color = Color.Black)
                            }
                        }
                        .size(100.dp)
                )

                Box(
                    modifier = Modifier
                        .drawWithCache {
                            val roundedPolygon = RoundedPolygon(
                                numVertices = 4,
                                radius = size.minDimension / 2,
                                centerX = size.width / 2,
                                centerY = size.height / 2,
                                rounding = CornerRounding(
                                    size.minDimension / 10f,
                                    smoothing = 0.1f
                                )
                            )
                            val roundedPolygonPath = roundedPolygon
                                .toPath()
                                .asComposePath()
                            onDrawBehind {
                                drawPath(roundedPolygonPath, color = Color.Black)
                            }
                        }
                        .size(100.dp)
                )

                Box(
                    modifier = Modifier
                        .drawWithCache {
                            val roundedPolygon = RoundedPolygon(
                                numVertices = 5,
                                radius = size.minDimension / 2,
                                centerX = size.width / 2,
                                centerY = size.height / 2,
                                rounding = CornerRounding(
                                    size.minDimension / 10f,
                                    smoothing = 0.1f
                                )
                            )
                            val roundedPolygonPath = roundedPolygon
                                .toPath()
                                .asComposePath()
                            onDrawBehind {
                                drawPath(roundedPolygonPath, color = Color.Black)
                            }
                        }
                        .size(100.dp)
                )

                Box(
                    modifier = Modifier
                        .drawWithCache {
                            val roundedPolygon = RoundedPolygon(
                                numVertices = 6,
                                radius = size.minDimension / 2,
                                centerX = size.width / 2,
                                centerY = size.height / 2,
                                rounding = CornerRounding(
                                    size.minDimension / 10f,
                                    smoothing = 0.1f
                                )
                            )
                            val roundedPolygonPath = roundedPolygon
                                .toPath()
                                .asComposePath()
                            onDrawBehind {
                                drawPath(roundedPolygonPath, color = Color.Black)
                            }
                        }
                        .size(100.dp)
                )
            }


        }


        item {
            TextHead(text = "变形形状")
            Row {
                Box(
                    modifier = Modifier
                        .drawWithCache {
                            val triangle = RoundedPolygon(
                                numVertices = 3,
                                radius = size.minDimension / 2f,
                                centerX = size.width / 2f,
                                centerY = size.height / 2f,
                                rounding = CornerRounding(
                                    size.minDimension / 10f,
                                    smoothing = 0.1f
                                )
                            )
                            val square = RoundedPolygon(
                                numVertices = 4,
                                radius = size.minDimension / 2f,
                                centerX = size.width / 2f,
                                centerY = size.height / 2f
                            )

                            val morph = Morph(start = triangle, end = square)
                            val morphPath = morph
                                .toPath(progress = 0.5f)
                                .asComposePath()

                            onDrawBehind {
                                drawPath(morphPath, color = Color.Black)
                            }
                        }
                        .size(100.dp)
                )

                Box(
                    modifier = Modifier
                        .drawWithCache {
                            val triangle = RoundedPolygon(
                                numVertices = 3,
                                radius = size.minDimension / 2f,
                                centerX = size.width / 2f,
                                centerY = size.height / 2f,
                                rounding = CornerRounding(
                                    size.minDimension / 10f,
                                    smoothing = 0.1f
                                )
                            )
                            val square = RoundedPolygon(
                                numVertices = 4,
                                radius = size.minDimension / 2f,
                                centerX = size.width / 2f,
                                centerY = size.height / 2f
                            )

                            val morph = Morph(start = triangle, end = square)
                            val morphPath = morph
                                .toPath(progress = 0.8f)
                                .asComposePath()

                            onDrawBehind {
                                drawPath(morphPath, color = Color.Black)
                            }
                        }
                        .size(100.dp)
                )

                Box(
                    modifier = Modifier
                        .drawWithCache {
                            val triangle = RoundedPolygon(
                                numVertices = 4,
                                radius = size.minDimension / 2f,
                                centerX = size.width / 2f,
                                centerY = size.height / 2f,
                                rounding = CornerRounding(
                                    size.minDimension / 10f,
                                    smoothing = 0.1f
                                )
                            )
                            val square = RoundedPolygon(
                                numVertices = 5,
                                radius = size.minDimension / 2f,
                                centerX = size.width / 2f,
                                centerY = size.height / 2f
                            )

                            val morph = Morph(start = triangle, end = square)
                            val morphPath = morph
                                .toPath(progress = 0.5f)
                                .asComposePath()

                            onDrawBehind {
                                drawPath(morphPath, color = Color.Black)
                            }
                        }
                        .size(100.dp)
                )

            }


            val infiniteAnimation = rememberInfiniteTransition(label = "infinite animation")
            val morphProgress = infiniteAnimation.animateFloat(
                initialValue = 0f,
                targetValue = 1f,
                animationSpec = infiniteRepeatable(
                    tween(500),
                    repeatMode = RepeatMode.Reverse
                ),
                label = "morph"
            )
            Box(
                modifier = Modifier
                    .drawWithCache {
                        val triangle = RoundedPolygon(
                            numVertices = 3,
                            radius = size.minDimension / 2f,
                            centerX = size.width / 2f,
                            centerY = size.height / 2f,
                            rounding = CornerRounding(
                                size.minDimension / 10f,
                                smoothing = 0.1f
                            )
                        )
                        val square = RoundedPolygon(
                            numVertices = 4,
                            radius = size.minDimension / 2f,
                            centerX = size.width / 2f,
                            centerY = size.height / 2f
                        )

                        val morph = Morph(start = triangle, end = square)
                        val morphPath = morph
                            .toPath(progress = morphProgress.value)
                            .asComposePath()

                        onDrawBehind {
                            drawPath(morphPath, color = Color.Black)
                        }
                    }
                    .size(100.dp)
            )

        }


        item {
            TextHead(text = "使用多边形作为裁剪")
            val hexagon = remember {
                RoundedPolygon(
                    6,
                    rounding = CornerRounding(0.2f)
                )
            }
            val clip = remember(hexagon) {
                RoundedPolygonShape(polygon = hexagon)
            }
            Box(
                modifier = Modifier
                    .clip(clip)
                    .background(MaterialTheme.colorScheme.secondary)
                    .size(200.dp)
            ) {
                Text(
                    "Hello Compose",
                    color = MaterialTheme.colorScheme.onSecondary,
                    modifier = Modifier.align(Alignment.Center)
                )
            }

        }

        item {
            val hexagon = remember {
                RoundedPolygon(
                    6,
                    rounding = CornerRounding(0.2f)
                )
            }
            val clip = remember(hexagon) {
                RoundedPolygonShape(polygon = hexagon)
            }
            Box(
                modifier = Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                Image(
                    painter = painterResource(id = R.drawable.ic_dog1),
                    contentDescription = "Dog",
                    contentScale = ContentScale.Crop,
                    modifier = Modifier
                        .graphicsLayer {
                            this.shadowElevation = 6.dp.toPx()
                            this.shape = clip
                            this.clip = true
                            this.ambientShadowColor = Color.Black
                            this.spotShadowColor = Color.Black
                        }
                        .size(200.dp)

                )
            }
        }

        item {
            TextHead(text = "点击时变形按钮")

            val shapeA = remember {
                RoundedPolygon(
                    6,
                    rounding = CornerRounding(0.2f)
                )
            }
            val shapeB = remember {
                RoundedPolygon.star(
                    6,
                    rounding = CornerRounding(0.1f)
                )
            }
            val morph = remember {
                Morph(shapeA, shapeB)
            }
            val interactionSource = remember {
                MutableInteractionSource()
            }
            val isPressed by interactionSource.collectIsPressedAsState()
            val animatedProgress = animateFloatAsState(
                targetValue = if (isPressed) 1f else 0f,
                label = "progress",
                animationSpec = spring(dampingRatio = 0.4f, stiffness = Spring.StiffnessMedium)
            )
            Box(
                modifier = Modifier
                    .size(200.dp)
                    .padding(8.dp)
                    .clip(MorphPolygonShape(morph, animatedProgress.value))
                    .background(Color(0xFF80DEEA))
                    .size(200.dp)
                    .clickable(interactionSource = interactionSource, indication = null) {
                    }
            ) {
                Text("Hello", modifier = Modifier.align(Alignment.Center))
            }

        }

        item {
            TextHead(text = "为形状无限变形添加动画效果")
            RotatingScallopedProfilePic()
        }

    }

}

private class CustomRotatingMorphShape(
    private val morph: Morph,
    private val percentage: Float,
    private val rotation: Float
) : Shape {

    private val matrix = Matrix()
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        // Below assumes that you haven't changed the default radius of 1f, nor the centerX and centerY of 0f
        // By default this stretches the path to the size of the container, if you don't want stretching, use the same size.width for both x and y.
        matrix.scale(size.width / 2f, size.height / 2f)
        matrix.translate(1f, 1f)
        matrix.rotateZ(rotation)

        val path = morph.toPath(progress = percentage).asComposePath()
        path.transform(matrix)

        return Outline.Generic(path)
    }
}

@Preview
@Composable
private fun RotatingScallopedProfilePic() {
    val shapeA = remember {
        RoundedPolygon(
            12,
            rounding = CornerRounding(0.2f)
        )
    }
    val shapeB = remember {
        RoundedPolygon.star(
            12,
            rounding = CornerRounding(0.2f)
        )
    }
    val morph = remember {
        Morph(shapeA, shapeB)
    }
    val infiniteTransition = rememberInfiniteTransition("infinite outline movement")
    val animatedProgress = infiniteTransition.animateFloat(
        initialValue = 0f,
        targetValue = 1f,
        animationSpec = infiniteRepeatable(
            tween(2000, easing = LinearEasing),
            repeatMode = RepeatMode.Reverse
        ),
        label = "animatedMorphProgress"
    )
    val animatedRotation = infiniteTransition.animateFloat(
        initialValue = 0f,
        targetValue = 360f,
        animationSpec = infiniteRepeatable(
            tween(6000, easing = LinearEasing),
            repeatMode = RepeatMode.Reverse
        ),
        label = "animatedMorphProgress"
    )
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        Image(
            painter = painterResource(id = R.drawable.ic_dog1),
            contentDescription = "Dog",
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .clip(
                    CustomRotatingMorphShape(
                        morph,
                        animatedProgress.value,
                        animatedRotation.value
                    )
                )
                .size(200.dp)
        )
    }
}


private class MorphPolygonShape(
    private val morph: Morph,
    private val percentage: Float
) : Shape {

    private val matrix = Matrix()
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        // Below assumes that you haven't changed the default radius of 1f, nor the centerX and centerY of 0f
        // By default this stretches the path to the size of the container, if you don't want stretching, use the same size.width for both x and y.
        matrix.scale(size.width / 2f, size.height / 2f)
        matrix.translate(1f, 1f)

        val path = morph.toPath(progress = percentage).asComposePath()
        path.transform(matrix)
        return Outline.Generic(path)
    }
}

fun RoundedPolygon.getBounds() = calculateBounds().let { Rect(it[0], it[1], it[2], it[3]) }
private class RoundedPolygonShape(
    private val polygon: RoundedPolygon,
    private var matrix: Matrix = Matrix()
) : Shape {
    private var path = Path()
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        path.rewind()
        path = polygon.toPath().asComposePath()
        matrix.reset()
        val bounds = polygon.getBounds()
        val maxDimension = max(bounds.width, bounds.height)
        matrix.scale(size.width / maxDimension, size.height / maxDimension)
        matrix.translate(-bounds.left, -bounds.top)

        path.transform(matrix)
        return Outline.Generic(path)
    }
}


@Composable
private fun TextHead(text: String) {
    Text(text, fontWeight = FontWeight.Bold, color = Color.Red)
}